home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 11
/
FM Towns Free Software Collection 11.iso
/
t_os
/
game
/
pr
/
src
/
prgame.c
< prev
next >
Wrap
Text File
|
1995-08-18
|
11KB
|
437 lines
/*===============================
"prgame.c" : racing game
===============================*/
#include <fmcfrb.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "timekh.h"
#include "pad.h"
#include "prdef.h"
#define startTM() TIM_rdcalendar(&st)
#define waitTM(_t) do{TIM_rdcalendar( &et );}while(getTime(st,et)<(_t))
#define readPad() do{_outb(PADOUT,COM0);}while((_inb(PAD1IN)&COMIN)!=0);\
pad=_inb(PAD1IN);
void putmap( int x0, int y0, int z0, vect ex, vect ey, vect ez );
void putcar( int x0, int y0, int z0, vect ex, vect ey, vect ez, int cpol );
int mycar( short x, short y, short z, int ang, vect kv );
int encar( short x, short y, short z, int ang, vect kv, int col, int pol );
void writeScreen();
void clearVram(int a, int b, int c);
int onRoad( int x, int y, int n );
void putMess( char *str, int col );
void putLapTime( int lap, int time, int best );
void putRestTime( int rt );
void clearMess();
void putSpd( int spd );
void putlmap();
void setLap( short blp, short flp );
#define putExTime() putMess("Extended Time",14)
static TIM_CALEN st,et;
#define CPMAX 10
#define PI 3.14159265
#define MaxSpd 8000
#define ACL 250
#define BRK 300
//#define GRP 40
#define Ekt 998
#define ANG(_a) _a = (_a+20000)%10000
extern poly car[3];
extern rdata *road;
#define slipFlag(col) car[0].type=car[1].type= \
(col)==0?C32K(31,0,0):C32K(0,31,0)
#define onRdFlag(col) car[2].type=((col)>=0?C32K(31,0,15):C32K(20,20,0))
extern int _time[20],_dn;
extern int *_cos,*_sin;
extern short rd;
extern short cpn, *cp;
extern short *exTime;
extern way *way1st,*waybst;
way *ecs[6]; //={waybst,waybst+1,waybst+2,way1st,way1st+1,way1st+2};
way cway,pw1st,pwbst;
extern int maxtime,h;
extern int lapFlag,wayFlag;
int pflap=0;
/*======================
ベクトル加工関数
======================*/
vect ortholize( vect vec )
{
int l ;
l = sqrt(vec.x*vec.x+vec.y*vec.y+vec.z*vec.z)*10 ;
if(l==0){
vec.z = 1000 ;
return vec;
}
vec.x = (int)vec.x*10000/l ;
vec.y = (int)vec.y*10000/l ;
vec.z = (int)vec.z*10000/l ;
return vec ;
}
vect exProduct( vect v1, vect v2 )
{
vect kv;
int x1=v1.x,y1=v1.y,z1=v1.z ;
int x2=v2.x,y2=v2.y,z2=v2.z ;
kv.x = (y1*z2 - z1*y2)/1000 ;
kv.y = (z1*x2 - x1*z2)/1000 ;
kv.z = (x1*y2 - y1*x2)/1000 ;
return kv ;
}
/*=========================
game 3D test version
=========================*/
void game( short sx,short sy,short sang )
{
int pol, i,j;
int x,y, spd=0,acl;
int ang,mang;
int ecx,ecy,ectime[6] = {-1,-1,-1,-1,-1,-1};
int sfc, grip, onRd=0, ekt;
int lapTime=30000, lap=0,messTime;
int restTime=6000;
char lapflag[CPMAX]=0;
char pad;
int mess=0,viewpt=1,viewtime=0;
h = 150; // [cm]
int height=road[0].pz,xx,yy;
vect kv=road[0].k;
vect zv; zv.x=0,zv.y=0,zv.z=1000;
int brkf=0,bf,bs;
vect ex,ey,ez ;
int vx,vy,vz, cs,sn ;
for(i=0; i<cpn; ++i) lapflag[i]=1 ;
for(i=0; i<6; ++i ) ecs[i] = way1st+i ;
pw1st.ltime=0 ;
pwbst.ltime=0 ;
x=sx*100, y=sy*100;
ang=mang=sang*10;
grip = (maxtime*MaxSpd*5/PI/1500)*MaxSpd; //*5000/Pi/150000/10
ekt=100000;
for(i=0; i<maxtime; ++i)
ekt = ekt*Ekt/1000;
ekt/=100;
putlmap();
putRestTime(-1) ;
while(1)
{
startTM();
readPad();
// エスケープ
if(PUSH(PADRUN+PADSEL)) {
j=0; break;
}
// 視点変更
else if(PUSH(PADSEL)&&viewtime<=0)
{
viewpt++; viewpt%=3;
viewtime=50 ;
}
if( viewtime>0 ) viewtime-=maxtime;
// スタート時のハンドル固定
if( lap==0 ) pad = ~(PADA);
// ハンドルの操作
if(PUSH(PADU)) i = 120000;
else if(PUSH(PADD)) i = 30000;
else i = 60000;
if(PUSH(PADL)) ang -= maxtime*spd*5000/PI/i/10;
if(PUSH(PADR)) ang += maxtime*spd*5000/PI/i/10;
ANG(ang);
// 加速
acl=0;
brkf=0;
if (PUSH(PADA)&&PUSH(PADB)) acl = ACL*2/3;
else {
if (PUSH(PADA)) acl = ACL;
if (PUSH(PADB)) acl =-BRK,brkf=1;
}
// コース位置確認
onRd=onRoad( x,y,onRd );
if( onRd<0 ) // コース外
acl -= BRK*2/3;
onRdFlag(onRd);
// 高度算出
if( onRd>=0 ){
xx = x-road[onRd].px[0]*100 ;
yy = y-road[onRd].py[0]*100 ;
kv = road[onRd].k ;
//if ( 0!=kv.z) {
height = road[onRd].pz-(kv.x*xx+kv.y*yy)/kv.z/10 ;
//}
//else {
// height = road[onRd].pz ;
// printf("onRd=[%d],(kz==0)\n",onRd);
//}
}else {
kv.x = kv.y = 0 ;
kv.z = 1000 ;
}
ANG(mang);
bf = kv.x*_cos[mang/10]+kv.y*_sin[mang/10] ;
bs =-kv.x*_sin[mang/10]+kv.y*_cos[mang/10] ;
// スリップの計算
i = (ang-mang+25000)%10000-5000; //進行方向とのずれ角
//bs = bs ; // bs=bs/1000/100*g*10000 ;
sfc = spd*i - bs ; // sin(i)*v *10000-bs
// printf("bs=%d,sfc=%d,(bs&sfc)=%d\n",
// bs,spd*i,sfc);
if (_abs(sfc)<=grip||spd==0) {
mang = ang;
j = 0;
} else {
if (sfc>0)
mang += (grip-bs)/spd;
else
mang -= (grip+bs)/spd;
j = 1;
}
slipFlag(j);
// i = (ang-mang+20000)%10000;
// mang += acl*_sin[i/10]*100/spd/PI;
// acl = acl*_cos[i/10]/100;
ANG(mang);
acl += bf/600 ; // 600->適当 (^^;
spd = ( spd*ekt + MaxSpd*(1000-ekt)*acl/ACL )/1000;
if (spd<0) spd=0 ;
// 位置の更新
x += spd*maxtime*_cos[mang/10]/1000;
y += spd*maxtime*_sin[mang/10]/1000;
// ExtendTime 表示と Lap 処理
if( onRd>=0 )
{
for(i=0; i<cpn; ++i)
{
if( onRd==cp[i] && lapflag[i]==0 )
{
lapflag[i] = 1;
restTime += exTime[i]*100;
if( mess!=0 ) clearMess();
putExTime();
mess = 2;
messTime = 500;
cway.stime[i] = lapTime ;
break;
}
}
}
// メッセージの消去
if( mess!=0 ){
messTime -= maxtime;
if( messTime<0 )
{
clearMess();
mess=0;
}
}
// LapTime の表示等 ラップ更新時の処理
if( onRd==0 )
{
for(i=0,j=1; i<cpn; ++i) j *= lapflag[i] ;
if( j==1 ){
if( lap==0 ) restTime=6000;
else cway.ltime = lapTime;
if( lap==1 )
{
memcpy( &pw1st, &cway, sizeof(way) );
for(i=0; i<6; ++i ) ecs[i] = waybst+i;
}
if( lap!=0 )
{
for(i=0; i<6; i++) ectime[i]=maxtime*3*(6-i);
if (pwbst.ltime>=lapTime||pwbst.ltime==0) {
memcpy( &pwbst, &cway, sizeof(way) );
}
}
putLapTime(lap,lapTime,pwbst.ltime);
mess=1, messTime=600 ;
lap++, lapTime=0 ;
memset( lapflag, 0, cpn );
}
}
// 走行データの記録
if( lap!=0 && lapTime<10000 )
{
cway.pt[lapTime].x=x/100;
cway.pt[lapTime].y=y/100;
cway.pt[lapTime].z=height;
cway.ang[lapTime]=ang/10;
}
lapTime += maxtime;
// RestTime の処理
restTime -= maxtime;
if( lap>0 && restTime<0 ){
j = 1;
break;
}
// 車ポリゴンのセット
pol=mycar( x/100,y/100,height,ang/10,kv );
for(j=0;j<6;j++)
{
if( ecs[j]->ltime!=0 ){
if( ectime[j]<0 ){
ecx = x/100 + _cos[sang]*(6-j)/2; // 5m*(6-j)
ecy = y/100 + _sin[sang]*(6-j)/2;
i = C32K((j+2)%2,((j+2)/2)%2,((j+2)/4)%2);
pol = encar( ecx, ecy, height, sang, kv, i, pol );
i = onRoad( ecx*100,ecy*100,rd-10 );
if( i>=0 && i<10 ) ectime[j]=0;
}else {
if( ectime[j]<=ecs[j]->ltime ){
i = C32K((j+2)%2,((j+2)/2)%2,((j+2)/4)%2);
pol=encar( ecs[j]->pt[ectime[j]].x,
ecs[j]->pt[ectime[j]].y,
ecs[j]->pt[ectime[j]].z,
ecs[j]->ang[ectime[j]],
zv/*ecs[j]->kv[ectime[j]]*/, i, pol
);
ectime[j]+=maxtime;
}
}
}
}
// 画面表示
cs = cos(_PI*2*mang/10000)*1000;
sn = sin(_PI*2*mang/10000)*1000;
switch(viewpt){
case 1:
ey.x = kv.z*cs /1000 ;
ey.y = kv.z*sn /1000 ;
ey.z = -(kv.x*cs + kv.y*sn) /1000 ;
ey = ortholize( ey ) ;
ez.x = (1000-sn)*kv.x /1000 ;
ez.y = (1000-cs)*kv.y /1000 ;
ez.z = kv.z ;
ez = ortholize( ez ) ;
ex = exProduct( ez,ey ) ; // 左手系
vx = x/10-ey.x*h/400+ez.x*h/1000 ; // x,y[mm]
vy = y/10-ey.y*h/400+ez.y*h/1000 ; // h,height[cm]
vz = height-ey.z*h/400+ez.z*h/1000 ; // vx-z[cm]
break ;
case 2:
ey.x = kv.z*cs /1000 ;
ey.y = kv.z*sn /1000 ;
ey.z = -(kv.x*cs + kv.y*sn) /1000 ;
ey = ortholize( ey ) ;
ez.x = (1000-sn)*kv.x /1000 ;
ez.y = (1000-cs)*kv.y /1000 ;
ez.z = kv.z ;
ez = ortholize( ez ) ;
ex = exProduct( ez,ey ) ; // 左手系
vx = x/10-ey.x*h/180+ez.x*h/500 ; // x,y[mm]
vy = y/10-ey.y*h/180+ez.y*h/500 ; // h,height[cm]
vz = height-ey.z*h/180+ez.z*h/500 ; // vx-z[cm]
break ;
default :
ey.x = cs*5000/5099 ;
ey.y = sn*5000/5099 ;
ey.z = -1000*1000/5099 ;
ez.x = cs*1000/5099 ;
ez.y = sn*1000/5099 ;
ez.z = 1000*5000/5099 ;
ex = exProduct( ez,ey ) ; // 左手系
vx = x/10-ey.x*h/33+ez.x*h/100 ; // x,y[mm]
vy = y/10-ey.y*h/33+ez.y*h/100 ; // h,height[cm]
vz = height-ey.z*h/33+ez.z*h/100 ; // vx-z[cm]
break ;
}
#if debug>=2
if(brkf){
printf("ex[%d,%d,%d]ey[%d,%d,%d]ez[%d,%d,%d],kv[%d,%d,%d]\n",
ex.x,ex.y,ex.z,
ey.x,ey.y,ey.z,
ez.x,ez.y,ez.z,
kv.x,kv.y,kv.z );
}
#endif
clearVram( ex.z,ey.z,ez.z ) ;
putmap( vx,vy,vz, ex,ey,ez ) ;
putcar( vx,vy,vz, ex,ey,ez, pol ) ;
putSpd( spd*280/MaxSpd ) ;
if(lap>0) putRestTime(restTime/100) ;
writeScreen() ;
// カウント終了処理
TIM_rdcalendar( &et ) ;
i=getTime(st,et) ;
if (i<20) ++_time[i] ;
++_dn ;
// if (_dn>=300) break ;
waitTM(maxtime) ;
}
if( mess!=0 ){
clearMess();
mess=0;
}
// if( j==1 ); // TimeOver
// if( j==0 ); // Retire
i = (pwbst.ltime==0 ? 30000:pwbst.ltime) ;
j = (pw1st.ltime==0 ? 30000:pw1st.ltime) ;
setLap( (short)i, (short)j );
pflap = pw1st.ltime; // ?
// データの補間
extern makeUpWay( way *wd, int st, int ed );
for(i=0; i<pw1st.ltime; i+=maxtime)
makeUpWay( &pw1st,i,i+maxtime );
for(i=0; i<pwbst.ltime; i+=maxtime)
makeUpWay( &pwbst,i,i+maxtime );
// way データの更新
if (pw1st.ltime!=0&&(pw1st.ltime<=way1st[5].ltime||way1st[5].ltime==0))
{
for(i=0; i<6; ++i){
if (pw1st.ltime<=way1st[i].ltime||way1st[i].ltime==0)
break ;
}
_rmemcpy( &way1st[i+1], &way1st[i], sizeof(way)*(5-i) );
_rmemcpy( &way1st[i], &pw1st, sizeof(way) );
wayFlag = 1;
}
if (pwbst.ltime!=0&&(pwbst.ltime<=waybst[5].ltime||waybst[5].ltime==0))
{
for(i=0; i<6; ++i){
if (pwbst.ltime<=waybst[i].ltime||waybst[i].ltime==0)
break ;
}
_rmemcpy( &waybst[i+1], &waybst[i], sizeof(way)*(5-i) );
_rmemcpy( &waybst[i], &pwbst, sizeof(way) );
wayFlag = 1;
}
}